using System;
using System.Collections;
using System.IO;
using System.Text;


namespace Ultima {
  public class StringList {
    private static byte[] m_Buffer = new byte[1024];
    private readonly StringEntry[] m_Entries;

    private readonly Hashtable m_EntTable;
    private readonly string m_Language;
    private readonly Hashtable m_Table;

    public StringList( string language ) {
      this.m_Language = language;
      this.m_Table = new Hashtable();
      this.m_EntTable = new Hashtable();

      string path = Client.GetFilePath( String.Format( "cliloc.{0}", language ) );

      if ( path == null || !File.Exists( path ) ) {
        Console.WriteLine( "Error! Unable to open {0}!", path );
        this.m_Entries = new StringEntry[0];
        return;
      }

      var list = new ArrayList();

      using (
        var bin = new BinaryReader( new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read ), Encoding.UTF8 ) ) {
        bin.ReadInt32();
        bin.ReadInt16();

        try {
          while ( true ) {
            int number = bin.ReadInt32();
            bin.ReadByte();
            int length = bin.ReadInt16();

            if ( length > m_Buffer.Length )
              m_Buffer = new byte[( length + 1023 ) & ~1023];

            bin.Read( m_Buffer, 0, length );

            try {
              StringEntry ent;
              string text = Encoding.UTF8.GetString( m_Buffer, 0, length );

              ent = new StringEntry( number, text );
              list.Add( ent );
              this.m_EntTable[number] = ent;
              this.m_Table[number] = text;
            } catch {
            }
          }
        } catch ( EndOfStreamException ) {
          // end of file.  stupid C#.
        }
      }

      this.m_Entries = (StringEntry[])list.ToArray( typeof( StringEntry ) );
    }

    public StringEntry[] Entries {
      get { return this.m_Entries; }
    }
    public Hashtable Table {
      get { return this.m_Table; }
    }
    public string Language {
      get { return this.m_Language; }
    }

    public string Format( int num, params object[] args ) {
      var ent = this.m_EntTable[num] as StringEntry;

      if ( ent != null )
        return ent.Format( args );
      else
        return String.Format( "CliLoc string {0}/{1} not found!", num, this.m_EntTable.Count );
    }

    public string SplitFormat( int num, string argstr ) {
      var ent = this.m_EntTable[num] as StringEntry;

      if ( ent != null )
        return ent.SplitFormat( argstr );
      else
        return String.Format( "CliLoc string {0}/{1} not found!", num, this.m_EntTable.Count );
    }
  }
}